package com.ruoyi.system.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.bean.CglibUtil;
import com.ruoyi.system.domain.params.CustomerSaveParams;
import com.ruoyi.system.domain.params.SaveOrderParams;
import com.ruoyi.system.domain.vo.CacheCustomerVo;
import com.ruoyi.system.domain.vo.UmsCustomerInfoVo;
import com.ruoyi.system.domain.vo.UmsCustomerListVo;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.UmsCustomerMapper;
import com.ruoyi.system.domain.UmsCustomer;
import com.ruoyi.system.service.IUmsCustomerService;

import javax.annotation.Resource;

/**
 * 客户Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-26
 */
@Service
public class UmsCustomerServiceImpl implements IUmsCustomerService {
    @Resource
    private UmsCustomerMapper umsCustomerMapper;
    @Resource
    private SysDictDataMapper sysDictDataMapper;
    @Resource
    private RedisCache redisCache;

    // 用户编码占用锁
    public static final String USER_CODE_CACHE = "user:code:lock:%s";

    // 用户名称占用锁(客户临时信息）
    public static final String USER_NAME_CACHE = "user:name:lock:%s";

    /**
     * 查询客户
     *
     * @param userId 客户主键
     * @return 客户
     */
    @Override
    public UmsCustomer selectUmsCustomerByUserId(Integer userId) {
        UmsCustomer customer = umsCustomerMapper.selectUmsCustomerByUserId(userId);
        if (customer != null) {
            customer.setPassword(null);
        }
        return customer;
    }

    /**
     * 查询客户列表
     *
     * @param umsCustomer 客户
     * @return 客户
     */
    @Override
    public List<UmsCustomerListVo> selectUmsCustomerList(UmsCustomer umsCustomer) {
        return umsCustomerMapper.selectUmsCustomerList(umsCustomer);
    }

    /**
     * 新增客户
     * @param umsCustomer 客户
     * @return 结果
     */
    @Override
    public int insertUmsCustomer(UmsCustomer umsCustomer) {
        boolean verifyParams = StringUtils.isEmpty(umsCustomer.getUsername()) || StringUtils.isEmpty(umsCustomer.getCode());
        if (verifyParams) {
            throw new ServiceException("非法参数");
        }
        // 验证客户代码是否过期
        CacheCustomerVo cacheCustomer = redisCache.getCacheObject(String.format(USER_NAME_CACHE, umsCustomer.getUsername()));
        if (ObjectUtils.isEmpty(cacheCustomer)) {
            throw new ServiceException("客户代码已失效");
        }
        umsCustomer.setUsername(umsCustomer.getUsername().trim());
        if (!umsCustomer.getUsername().equals(cacheCustomer.getUsername())) {
            throw new ServiceException("用户代码与名称不符合");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        umsCustomer.setPassword(passwordEncoder.encode(cacheCustomer.getPassword()));
        redisCache.deleteObject(String.format(USER_CODE_CACHE, umsCustomer.getCode()));
        return umsCustomerMapper.insertUmsCustomer(umsCustomer);
    }

    /**
     * 生成用户编码
     * @param username
     * @return
     */
    @Override
    public String createUserCode(String username) {
        UmsCustomer umsCustomer = umsCustomerMapper.selectUserCustomerByName(username.trim());
        if (umsCustomer != null) {
            throw new ServiceException("用户名已存在");
        }
        CacheCustomerVo customerInfo = createCode(username);
        if (customerInfo == null) {
            redisCache.deleteObject(String.format(USER_NAME_CACHE,username));
            throw new ServiceException("用户信息获取发生错误！");
        }
        return customerInfo.getCode();
    }

    /**
     * 修改客户
     *
     * @param umsCustomer 客户
     * @return 结果
     */
    @Override
    public int updateUmsCustomer(CustomerSaveParams umsCustomer) {
        if (umsCustomer.getUserId() == null) {
            throw new ServiceException("非法参数");
        }
        if (StringUtils.isNotEmpty(umsCustomer.getPassword())) {
            if (StringUtils.isEmpty(umsCustomer.getRepPassword())) {
                throw new ServiceException("确认密码不能为空");
            }
            if (!umsCustomer.getPassword().equals(umsCustomer.getRepPassword())) {
                throw new ServiceException("确认密码不一致");
            }
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            umsCustomer.setPassword(passwordEncoder.encode(umsCustomer.getPassword()));
        }
        umsCustomer.setCode(null);
        UmsCustomer customer = new UmsCustomer();
        BeanUtils.copyProperties(umsCustomer,customer);
        return umsCustomerMapper.updateUmsCustomer(customer);
    }

    /**
     * 批量删除客户
     *
     * @param userIds 需要删除的客户主键
     * @return 结果
     */
    @Override
    public int deleteUmsCustomerByUserIds(Long[] userIds) {
        return umsCustomerMapper.deleteUmsCustomerByUserIds(userIds);
    }

    /**
     * 删除客户信息
     *
     * @param userId 客户主键
     * @return 结果
     */
    @Override
    public int deleteUmsCustomerByUserId(Long userId) {
        return umsCustomerMapper.deleteUmsCustomerByUserId(userId);
    }

    /**
     * 客户端接口
     * 根据客户姓名获取客户账号详情，如果没这个账号就注册一个
     * @param name 客户姓名
     * @return
     */
    @Override
    public UmsCustomerInfoVo clientGetCustomerInfoByName(String name) {
        name = name.trim().replaceAll(" ", "");
        if (StringUtils.isEmpty(name)) {
            throw new ServiceException("客户名称不能为空");
        }
        UmsCustomerInfoVo details = new UmsCustomerInfoVo();
        UmsCustomer customerByName = umsCustomerMapper.getCustomerByName(name);
        if (!ObjectUtils.isEmpty(customerByName)) {
            CglibUtil.copy(customerByName,details);
            details.setUserId(customerByName.getUserId());
            if (customerByName.getNationality() != null) {
                SysDictData sysDictData = sysDictDataMapper.selectDictDataById(Long.parseLong(customerByName.getNationality().toString()));
                details.setNationalityId(sysDictData.getDictValue());
                details.setNationalityName(sysDictData.getDictLabel());
            }
            return details;
        }
        details.setNationalityName("");
        CacheCustomerVo customerVo = createCode(name);
        if (customerVo == null) {
            redisCache.deleteObject(String.format(USER_NAME_CACHE,name));
            throw new ServiceException("用户信息获取发生错误！");
        }
        details.setCode(customerVo.getCode());
        details.setUsername(name);
        return details;
    }

    /**
     * 创建订单时返回合法客户
     * @return
     */
    @Override
    public UmsCustomer createOrderCustomerInfo(SaveOrderParams params) {
        // 判断客户是否有效
        if (params.getCustomerId() != null) {
            UmsCustomer customer = umsCustomerMapper.selectUmsCustomerByUserId(params.getCustomerId());
            if (customer == null) {
                throw new ServiceException("客户信息发生错误1");
            }
            return customer;
        }
//        if (StringUtils.isEmpty(params.getCustomerPhone())) {
//            throw new ServiceException("客户手机号不能为空");
//        }
        String cacheValue = redisCache.getCacheObject(String.format(USER_NAME_CACHE, params.getCustomerName()));
        if (StringUtils.isEmpty(cacheValue)) {
            throw new ServiceException("客户信息失效，请刷新后重试");
        }
        CacheCustomerVo customerInfo = JSON.parseObject(cacheValue, CacheCustomerVo.class);
        if (customerInfo == null) {
            throw new ServiceException("客户信息失效，请刷新后重试");
        }
        UmsCustomer nameExist = umsCustomerMapper.selectUserCustomerByName(customerInfo.getUsername());
        if (nameExist != null) {
            throw new ServiceException("用户名已存在");
        }
        // 插入新的客户
        UmsCustomer customer = new UmsCustomer();
        customer.setCode(customerInfo.getCode());
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        customer.setPassword(passwordEncoder.encode(customerInfo.getPassword()));
        customer.setUsername(customerInfo.getUsername());
        customer.setPhone(params.getCustomerPhone());
        customer.setCreateTime(new Date());
        customer.setCreateBy(StringUtils.isNotEmpty(params.getCreateBy()) ? params.getCreateBy() : params.getUpdateBy());
        if (StringUtils.isNotEmpty(params.getNationality())) {
            customer.setNationality(Integer.parseInt(params.getNationality()));
        }
        int i = umsCustomerMapper.insertUmsCustomer(customer);
        if (i == 0) {
            throw new ServiceException("添加新客户时发生错误");
        }
        return customer;
    }

    /**
     * 生成客户代码与密码
     * 密码规则 5 4 3
     * @return 用户编码-用户密码-用户名称
     */
    public CacheCustomerVo createCode(String name) {
        name = name.trim();
        String cacheValue = redisCache.getCacheObject(String.format(USER_NAME_CACHE, name));
        if (StringUtils.isNotEmpty(cacheValue)) {
            CacheCustomerVo cacheInfo = JSON.parseObject(cacheValue, CacheCustomerVo.class);
            return cacheInfo;
        }
        CacheCustomerVo vo = null;
        boolean flag = true;
        while (flag) {

            String code = "CS" + (int) ((Math.random() * 9 + 1) * 100000);
            String passwordCode = code.substring(code.length() - 3, code.length());

            String p1 = Integer.parseInt(Objects.toString(passwordCode.charAt(0))) + 5 + "";
            p1 = p1.length() > 1 ? Objects.toString(p1.charAt(1)) : p1;
            String p2 = Integer.parseInt(Objects.toString(passwordCode.charAt(1))) + 4 + "";
            p2 = p2.length() > 1 ? Objects.toString(p2.charAt(1)) : p2;
            String p3 = Integer.parseInt(Objects.toString(passwordCode.charAt(2))) + 3 + "";
            p3 = p3.length() > 1 ? Objects.toString(p3.charAt(1)) : p3;

            // 判断代码是否存在
            int customerByCode = umsCustomerMapper.getCustomerByCode(code);
            Boolean codeExist = redisCache.hasKey(String.format(USER_CODE_CACHE, code));
            if (customerByCode == 0 && !codeExist) {
                vo = new CacheCustomerVo();
                vo.setCode(code);
                vo.setUsername(name);
                vo.setPassword((p1 + p2 + p3));
                redisCache.setCacheObject(String.format(USER_CODE_CACHE,code),1,60 * 15, TimeUnit.SECONDS);
                redisCache.setCacheObject(String.format(USER_NAME_CACHE,name),JSON.toJSONString(vo),60 * 15, TimeUnit.SECONDS);
                flag = false;
            }
        }
        return vo;
    }

}
